<?php

namespace App\Controller;

use Cake\Core\Configure;
use Cake\Database\Schema\TableSchema;

use Djx\EasyJsonSchema\Manager\Parser;

use Cake\Datasource\ConnectionManager;

use Djx\EasyJsonSchema\Type\{
  Str, Obj, Arr, Num, Boolean
};


class AutoApisController extends AppController
{

    private $status;

    private $msg;

    private $pageTotal;

    public function initialize()
    {
        parent::initialize();
        $this->status    = (new Num)->mock(200)->desc('状态');
        $this->msg       = (new Str())->mock('Success')->desc('消息');
        $this->pageTotal = (new Num())->mock('@natural(10,100)')->desc('分页');
    }

    /*
   * create by phpstorm
   * author：DJX
   * date：2020.11.27
   * ps：获取数据库表自动创建基础API
   * */

    public function generate()
    {
        $data = $this->request->getData();
        if (empty($data['table'])) {
            return $this->G->error('请输入表名');
        }

        $tb = $data['table'];

        $conn  = ConnectionManager::get('default');
        $table = $conn->execute("SHOW TABLES LIKE '{$tb}'")->fetchAll();
        if (!empty($table)) {
            $tables  = $this->getTableLocator()->get($tb);
            $schema  = $tables->getSchema();
            $columns = $schema->columns();
            $fields  = [];
            $list    = [];
            foreach ($columns as $k => $v) {
                $field = $schema->getColumn($v);
                if (!in_array($v, ['is_delete', 'create_user', 'update_user'])
                    && $field['type'] != 'timestamp') {
                    $fields[$v] = $field;
                    $sp_id      = strrpos($v, '_id');
                    $sp_type    = strrpos($v, '_type');
                    if ($sp_id) {
                        $inTitle                 = $this->_inTitle($v, $sp_id, $field['comment']);
                        $fields[$inTitle['key']] = $inTitle['val'];
                    }
                    if ($sp_type) {
                        $inTitle                 = $this->_inTitle($v, $sp_type, $field['comment']);
                        $fields[$inTitle['key']] = $inTitle['val'];
                    }
                }
            }

            $list = [
              'url'  => "/getList",
              'json' => $this->_createList($fields),
            ];
            $info = [
              'url'  => "/getInfo",
              'json' => $this->_createInfo($fields),
            ];
            $add  = [
              'url'  => "/add",
              'json' => $this->_createAdd($fields),
            ];

            $update = [
              'url'  => "/update",
              'json' => $this->_createUpdate($fields),
            ];

            $this->G->success('Success', ['list' => $list, 'info' => $info, 'add' => $add, 'update' => $update]);
        } else {
            $this->G->error('表不存在');
        }
    }

    /**
     * 创建ListApi
     */
    private function _createList($fields = [])
    {
        $list = [];
        foreach ($fields as $key => $field) {
            $list[$key] = $this->_filterType($key, $field);
        }
        $json = (new Obj(
          [
            'memo'   => (new Obj(
              [
                "list"      => (new Arr)->items((new Obj($list))->requiredAll())->desc('消息列表'),
                "pageTotal" => $this->pageTotal,
              ]
            ))->requiredAll(),
            'status' => $this->status,
            'msg'    => $this->msg,
          ]
        ))->requiredAll();


        $body = (new Obj(
          [
            'title'        => (new Str)->mock('@ctitle')->desc('标题'),
            'verifyStatus' => (new Str)->mock('@natural(0,1)')->desc('审核状态'),
            'enabled'      => (new Str)->mock('@natural(0,1)')->desc('是否可用'),
          ]
        ));

        return [
          'body'     => Parser::run($body),
          'response' => Parser::run($json),
        ];
    }

    /**
     * 创建InfoApi
     */
    private function _createInfo($fields = [])
    {
        $list = [];
        foreach ($fields as $key => $field) {
            $list[$key] = $this->_filterType($key, $field);
        }
        $json = (new Obj(
          [
            'memo'   => ((new Obj($list))->requiredAll()),
            'status' => $this->status,
            'msg'    => $this->msg,
          ]
        ))->requiredAll();


        $body = (new Obj(
          [
            'id' => (new Str)->mock('@id')->desc('id'),
          ]
        ))->requiredAll();

        return [
          'body'     => Parser::run($body),
          'response' => Parser::run($json),
        ];
    }

    /**
     * 创建InfoApi
     */
    private function _createAdd($fields = [])
    {
        $list = [];
        foreach ($fields as $key => $field) {
            if (empty($field['virtual']) && $key != 'id') {
                $list[$key] = $this->_filterType($key, $field);
            }
        }
        $json = (new Obj(
          [
            'memo'   => ((new Obj())),
            'status' => $this->status,
            'msg'    => $this->msg,
          ]
        ))->requiredAll();


        $body = (new Obj($list))->requiredAll();

        return [
          'body'     => Parser::run($body),
          'response' => Parser::run($json),
        ];
    }

    /**
     * 创建InfoApi
     */
    private function _createUpdate($fields = [])
    {
        $list = [];
        foreach ($fields as $key => $field) {
            if (empty($field['virtual'])) {
                $list[$key] = $this->_filterType($key, $field);
            }
        }
        $json = (new Obj(
          [
            'memo'   => ((new Obj())),
            'status' => $this->status,
            'msg'    => $this->msg,
          ]
        ))->requiredAll();


        $body = (new Obj($list))->requiredAll();

        return [
          'body'     => Parser::run($body),
          'response' => Parser::run($json),
        ];
    }


    /**
     * 根据类型进行过滤
     */
    private function _filterType($key, $filed)
    {
        $type = $filed['type'];
        switch ($type) {
            case 'integer':
                $data = $this->_int($key, $filed);
                break;
            case 'tinyinteger':
                $data = $this->_tinyinteger($key, $filed);
                break;
            case 'decimal':
                $data = $this->_decimal($key, $filed);
                break;
            default:
                $data = $this->_string($key, $filed);
        }
        return $data;
    }

    /**
     * 去掉_id或_type 生成对应名称
     *
     * @param $key
     * @param $needle
     */
    private function _inTitle($key, $needle, $comment = '')
    {
        //        pr($needle);
        // 判断是否逻辑外键
        $newStr      = substr($key, 0, $needle);
        $data['key'] = $newStr . '_title';
        $data['val'] = [
          'type'    => 'string',
          'length'  => 60,
          'comment' => $comment . '对应名称',
          'virtual' => true,
        ];
        return $data;
    }

    /**
     * 字段类型为string时
     *
     * @param $filed
     */
    private function _string($key, $filed)
    {
        $json = (new Str);
        // 判断是否字符串为id
        if (preg_match("/id/i", $key)) {
            $json->mock('@id');
        } elseif (preg_match("/sn/i", $key)) {
            $json->mock('@guid');
        } elseif (preg_match("/title/i", $key)) {
            $json->mock('@ctitle');
        } elseif (preg_match("/name/i", $key)) {
            $json->mock('@cname');
        } elseif (preg_match("/desc|intro/i", $key)) {
            $json->mock('@cword(50)');
        } elseif (preg_match("/country/i", $key)) {
            $json->mock("中国");
        } elseif (preg_match("/zone/i", $key)) {
            $json->mock("@county");
        } elseif (preg_match("/time|date/i", $key)) {
            $json->mock("@datetime");
        } elseif (preg_match("/img|logo/i", $key)) {
            $json->mock("20/10/30/20103007201093019.jpg");
        } else {
            $json->mock("@string({$filed['length']})");
        }
        return $json->desc($filed['comment']);
    }

    /**
     * 字段类型为integer时
     *
     * @param $filed
     */
    private function _int($key, $filed)
    {
        $json = (new Num);
        // 判断是否字符串为id
        if (preg_match("/id/i", $key)) {
            $json->mock('@id');
        } elseif (preg_match("/sn/i", $key)) {
            $json->mock('@guid');
        } else {
            $json->mock("@integer({$filed['length']})");
        }
        return $json->desc($filed['comment']);
    }

    /**
     * 字段类型为tinyinteger时
     *
     * @param $filed
     */
    private function _tinyinteger($key, $filed)
    {
        $type = $filed['type'];

        // 从注释中提取数字
        $desc     = $filed['comment'];
        $patterns = "/\d+/";
        preg_match_all($patterns, $desc, $arr);
        $val     = empty($arr) ? null : join(",", $arr[0]);
        $natural = empty($val) ? '@natural(0,1)' : "@pick([{$val }])";
        return (new Num)->mock($natural)->desc($filed['comment']);
    }

    /**
     * 字段类型为decimal时
     *
     * @param $filed
     */
    private function _decimal($key, $filed)
    {
        $type = $filed['type'];
        return (new Num)->mock('@float(10,2)')->desc($filed['comment']);
    }

}

?>